package com.sec.android.app.myfiles.util.securefolder;

import android.content.Context;
import android.os.Environment;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.IOException;

public class HideUtils {

    private static final String TAG = HideUtils.class.getSimpleName();

    private static HideUtils hideUtilsInstance;

    private static Context context;

    public static HideUtils getInstance(Context c) {
        if (null == hideUtilsInstance) {
            hideUtilsInstance = new HideUtils();
            context = c;
        }
        return hideUtilsInstance;
    }

    //初始化securefolder根目录
    public void initPrivateRecovery() {
        File recoveryRootPathFile = new File(SecureConstants.privateRecoveryRootPath);
        if (!recoveryRootPathFile.exists()) {
            recoveryRootPathFile.mkdir();
        }

        File file = new File(SecureConstants.privateRecoveryRootPath + "/.nomedia");
        if (! file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void mkTestFiles() {

        mkTestRootFolder();

        String filePath1 = SecureConstants.externalStoragePath + "/Test/testfile1";
        String filePath2 = SecureConstants.externalStoragePath + "/Test/testfile2";
        File file = new File(filePath1);
        if (!file.exists()) {
            Log.e(TAG, "file1 not exist");
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        file = new File(filePath2);
        if (!file.exists()) {
            Log.e(TAG, "file2 not exist. mkdirs");
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void mkTestRootFolder() {
        String testRootPath = SecureConstants.externalStoragePath + "/Test";
        File file = new File(testRootPath);
        if (!file.exists()) {
            file.mkdir();
        }
    }

    public void testHideFile() {

        File oldFile1 = new File(SecureConstants.testFile1Path);
        File newFile1 = new File(SecureConstants.newFile1Path);

        File videoFile1 = new File(SecureConstants.testVideo1Path);
        File newVideoFile1 = new File(SecureConstants.newVideo1Path);

        Long timeStart = SystemClock.currentThreadTimeMillis();
        hideFile(oldFile1, newFile1);
        Long timeFile1 = SystemClock.currentThreadTimeMillis();

        hideFile(videoFile1, newVideoFile1);
        Long timeFile2 = SystemClock.currentThreadTimeMillis();

        Log.i(TAG, "file1 time: " + (timeFile1 - timeStart) + ", file2 time: " + (timeFile2 - timeFile1));
    }

    @Deprecated
    public void hideFile(File oldFile, File newFile) {
        if (oldFile != null && oldFile.exists()) {
            if (newFile == null) {
                Log.e(TAG, "hideFile failed. newFile is null");
            } else {
                if (newFile.exists()) {
                    //newFile已经存在
                }
            }
        }
    }

    public void moveToPrivateFolder(@NonNull File oldFile) {
        moveToPrivateFolderInternal(oldFile);

        //check oldFile is empty or not
        if (oldFile != null && oldFile.isDirectory()) {
            File[] childFiles = oldFile.listFiles();
            Log.i(TAG, "moveToPrivateFolder. childFiles length is " + childFiles.length);
            if (childFiles == null || childFiles.length == 0) {
                oldFile.delete();
            }
        }
    }

    private void moveToPrivateFolderInternal(@NonNull File oldFile) {
        String newFilePath = oldFile.getAbsolutePath().replace(SecureConstants.externalStorageAbsolutePath, SecureConstants.privateRecoveryRootPath);
        Log.i(TAG, "moveToPrivateFolderInternal. newFilePath is " + newFilePath);
        newFilePath = getHideSuffixPath(newFilePath, SecureConstants.privateRecoveryRootPath, false);
        Log.i(TAG, "moveToPrivateFolderInternal. newFilePath is " + newFilePath);
        File newFile = new File(newFilePath);
        if (! newFile.exists()) {
            Log.i(TAG, "moveToPrivateFolderInternal. newFilePath not exist. hideInternal...");
            hideFileInternal(oldFile, newFile);
        } else {
            //文件的情况先不考虑
            if (oldFile.isFile()) {
                oldFile.delete();
            } else if (oldFile.isDirectory()) {
                Log.i(TAG, "moveToPrivateFolderInternal. newFilePath already exist. list childs.. ");
                String[] childFileFolders = oldFile.list();
                if (childFileFolders != null) {
                    for (String childPath : childFileFolders) {
                        Log.i(TAG, "moveToPrivateFolderInternal. get child path: " + childPath);
                        File childFile = new File(childPath);
                        if (childFile != null) {
                            moveToPrivateFolder(childFile);
                        }
                    }
                }
            }
        }
    }

    public void removeFromPrivateFolder(@NonNull File oldFile) {
        removeFromPrivateFolderInternal(oldFile);

        //check oldFile is empty or not
        Log.i(TAG, "removeFromPrivateFolder oldFile path: " + oldFile.getAbsolutePath() + ", isDirectory ? " + oldFile.isDirectory());
        if (oldFile != null && oldFile.isDirectory()) {
            File[] childFiles = oldFile.listFiles();

            Log.i(TAG, "removeFromPrivateFolder. final length is " + childFiles.length);

            if (childFiles == null || childFiles.length == 0) {
                oldFile.delete();
            }
        }
    }

    private void removeFromPrivateFolderInternal(@NonNull File oldFile) {
        String newFilePath = oldFile.getAbsolutePath().replace(SecureConstants.privateRecoveryRootPath, SecureConstants.externalStorageAbsolutePath);
        Log.i(TAG, "removeFromPrivateFolderInternal. newFilePath is " + newFilePath);
        newFilePath = getHideSuffixPath(newFilePath, SecureConstants.externalStorageAbsolutePath, true);
        Log.i(TAG, "removeFromPrivateFolderInternal. newFilePath is " + newFilePath);

        File newFile = new File(newFilePath);
        if (! newFile.exists()) {
            Log.i(TAG, "removeFromPrivateFolderInternal. newFilePath not exist. hideInternal...");
            hideFileInternal(oldFile, newFile);
        } else {
            //文件的情况先不考虑
            if (oldFile.isFile()) {
                //TODO
                oldFile.delete();
            } else if (oldFile.isDirectory()) {
                Log.i(TAG, "removeFromPrivateFolderInternal. newFilePath already exist. list childs.. ");
                File[] childFiles = oldFile.listFiles();
                if (childFiles != null) {
                    for(File childFile : childFiles) {
                        Log.i(TAG, "removeFromPrivateFolderInternal. get child file path: " + childFile.getAbsolutePath());
                        removeFromPrivateFolder(childFile);
                    }
                }
            }
        }
    }

    private String getHideSuffixPath(@NonNull String filePath, String headerPath, boolean removeHide) {
        String hideSuffixPath = filePath;
        Log.i(TAG, "getHideSuffixPath. previous path is " + filePath);
        StringBuilder combindedPath = new StringBuilder();
        if (filePath != null && filePath.length() > 0) {
            filePath = filePath.replaceFirst(headerPath, "");
            Log.i(TAG, "getHideSuffixPath. after remove private recovery path. path is: " + filePath);

            String[] pathSegments = filePath.split("/");
            Log.i(TAG, "pathSegments length is " + pathSegments.length);
            if (pathSegments != null && pathSegments.length > 0) {
                for (int i = 0; i < pathSegments.length; i++) {
                    Log.i(TAG, "pathSegment" + i + " is " + pathSegments[i]);
                    if (!TextUtils.isEmpty(pathSegments[i])) {
                        combindedPath.append("/");
                        if (removeHide) {
                            int hideIndex = pathSegments[i].lastIndexOf(".hide");
                            if (hideIndex > 0) {
                                combindedPath.append(pathSegments[i].substring(0, hideIndex - 1));
                            }
                        } else {
                            combindedPath.append(pathSegments[i] + ".hide");
                        }
                    }
                }
            }
        }
        return (SecureConstants.privateRecoveryRootPath + combindedPath);
    }

    private void hideFileInternal(File oldFile, File newFile) {
        if (oldFile != null && oldFile.exists()) {
            boolean renameResult = oldFile.renameTo(newFile);
            if (! renameResult) {
                //直接调用renameTo api失败，要处理failed case
                Log.e(TAG, "call renameTo failed... srcFile: " + oldFile.getAbsolutePath() + ", destFile: " + newFile.getAbsolutePath());
                File targetParentFile = newFile.getParentFile();
                Log.i(TAG, "parent of target is : " + targetParentFile.getAbsolutePath());
                if (! targetParentFile.exists()) {
                    Log.i(TAG, "parent not exist. mkdirs and then renameTo again.");
                    targetParentFile.mkdirs();
                    boolean newRenameResult = oldFile.renameTo(newFile);
                    if (newRenameResult) {
                        Log.i(TAG, "yeah... renameTo succeed.");
                    } else {
                        Log.e(TAG, "renameTo failed again...");
                    }
                } else {
                    Log.i(TAG, "parent exist. skip.");
                }
            }
        }
    }

}
